/**
 * 
 */
package neptune.manager.validator.rules.topology;

import java.util.ArrayList;

import neptune.manager.NeptuneManager;
import neptune.manager.model.topology.MACAddress;
import neptune.manager.model.topology.NetworkInterface;
import neptune.manager.model.topology.Node;
import neptune.manager.model.topology.Topology;
import neptune.manager.storage.ExperimentRepositoryException;
import neptune.manager.utils.Logger.MessageType;
import neptune.manager.validator.ValidatorResult;
import neptune.manager.validator.ValidatorRule;
import neptune.manager.validator.Validator.Status;

/**
 * @author Roberto Bifulco [RobertoBifulco.it] [info@robertoBifulco.it]
 * 
 */
public class MACAddressesUniquenessRule extends ValidatorRule<Topology> {

	private NeptuneManager neptuneManager;

	public MACAddressesUniquenessRule(NeptuneManager neptuneManager) {
		super();
		this.neptuneManager = neptuneManager;
	}

	@Override
	public String getName() {
		return "MACAddressesUniquenessRule";
	}

	/**
	 * Verifica l'univocita' di un MAC Address. Se la topologia passata come
	 * argomento e' gia' presente nel repository, la copia nel repository viene
	 * ignorata.<br>
	 * <br>
	 * 
	 * E' importante notare che questa regola controlla l'univocita' nella
	 * definizione di un mac address, ma non presenta errori nel caso in cui ci
	 * siano mac address non definiti (ossia rappresentati da una stringa
	 * vuota).
	 * 
	 */
	@Override
	protected ValidatorResult validationAlgorithm(Topology toValidate,
			ValidatorResult result) {

		ArrayList<MACAddress> usedMACs = new ArrayList<MACAddress>(0);

		try {
			/*
			 * Recupero di tutte le topologie
			 */
			String[] expIds = neptuneManager.getExperimentsRepository()
					.getExperiments();

			// Creazione array contenente tutte le topologie compresa quella
			// attuale
			Topology[] topologies = new Topology[expIds.length + 1];
			topologies[topologies.length - 1] = toValidate;
			for (int i = 0; i < topologies.length - 1; i++) {
				topologies[i] = neptuneManager.getExperiment(expIds[i])
						.getTopology();
				if (topologies[i] != null) {
					if (toValidate.getName().equals(topologies[i].getName())) {
						topologies[i] = null; // Se questa topologia e' presente
						// nel repository, ignora la
						// copia in repository
					}
				}
			}
			/*
			 * ----
			 */

			for (Topology topology : topologies) {
				if (topology == null)
					continue;

				for (Node node : topology.getNodes()) {
					for (NetworkInterface netIf : node.getInterfaces()) {
						// Questo controllo ammette che siano presenti mac
						// address non definiti
						if (usedMACs.contains(netIf.getMacAddress())
								&& !netIf.getMacAddress().getAddress().equals(
										"")) {

							result.setStatus(Status.ERROR);
							result
									.getLog()
									.addMessage(
											"Duplicated MAC address '"
													+ netIf.getMacAddress()
													+ "' in interface '"
													+ netIf.getInterfaceName()
													+ "', node '"
													+ node.getId()
													+ "'. Error raised during topology '"
													+ topology.getName()
													+ "' examination.",
											MessageType.ERROR);
						} else
							usedMACs.add(netIf.getMacAddress());
					}
				}
			}

		} catch (ExperimentRepositoryException e) {
			result.setStatus(Status.ERROR);
			result.getLog().addMessage(
					"Unable to verify MAC Addresses uniqueness. Cause: "
							+ e.getMessage(), MessageType.ERROR);
		}

		return result;
	}
}
